module sim_top ();


wire            axi_aw_valid;
wire            axi_aw_ready;
wire   [47:0]   axi_aw_addr;
wire   [4:0]    axi_aw_id;
wire   [7:0]    axi_aw_len;
wire   [2:0]    axi_aw_size;
wire   [1:0]    axi_aw_burst;
wire   [3:0]    axi_aw_cache;
wire   [2:0]    axi_aw_prot;
wire            axi_w_valid;
wire            axi_w_ready;
wire   [127:0]  axi_w_data;
wire   [15:0]   axi_w_strb;
wire            axi_w_last;
wire            axi_b_valid;
wire            axi_b_ready;
wire   [4:0]    axi_b_id;
wire   [1:0]    axi_b_resp;
wire            axi_ar_valid;
wire            axi_ar_ready;
wire   [47:0]   axi_ar_addr;
wire   [4:0]    axi_ar_id;
wire   [7:0]    axi_ar_len;
wire   [2:0]    axi_ar_size;
wire   [1:0]    axi_ar_burst;
wire   [3:0]    axi_ar_cache;
wire   [2:0]    axi_ar_prot;
wire            axi_r_valid;
wire            axi_r_ready;
wire   [127:0]  axi_r_data;
wire   [4:0]    axi_r_id;
wire   [1:0]    axi_r_resp;
wire            axi_r_last;

wire   [1:0]    core_in_core_id;
wire   [7:0]    core_in_interrupt;
wire            core_in_ipi;


reg clk;
initial begin 
  clk = 0;
  forever begin
    #(2) clk = ~clk;
  end
end

reg reset;
initial begin
  reset = 0;
  #10;
  reset = 1;
  #80;
  reset = 0;
end


assign core_in_core_id = {1'b0, 1'b0};
assign core_in_interrupt = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
assign core_in_ipi = 1'b0;




`define RTL_MEM       slave_memory.x_f_spsram_large

integer i;
reg [31:0] mem_inst_temp [65536-1:0];
reg [31:0] mem_data_temp [65536-1:0];
integer j;
initial
begin
  $display("\t********* Init Program *********");
  $display("\t********* Wipe memory to 0 *********");
  for(i=0; i < 32'h16384; i=i+1)
  begin
    `RTL_MEM.ram0.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram1.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram2.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram3.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram4.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram5.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram6.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram7.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram8.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram9.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram10.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram11.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram12.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram13.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram14.mem[i][7:0] = 8'h0;
    `RTL_MEM.ram15.mem[i][7:0] = 8'h0;
  end

  $display("\t********* Read program *********");        
  $readmemh("inst.pat", mem_inst_temp);
  $readmemh("data.pat", mem_data_temp);

  $display("\t********* Load program to memory *********");
i=0;
for(j=0;i<32'h4000;i=j/4)
  begin
    `RTL_MEM.ram0.mem[i][7:0] = mem_inst_temp[j][31:24];
    `RTL_MEM.ram1.mem[i][7:0] = mem_inst_temp[j][23:16];
    `RTL_MEM.ram2.mem[i][7:0] = mem_inst_temp[j][15: 8];
    `RTL_MEM.ram3.mem[i][7:0] = mem_inst_temp[j][ 7: 0];
    j = j+1;
    `RTL_MEM.ram4.mem[i][7:0] = mem_inst_temp[j][31:24];
    `RTL_MEM.ram5.mem[i][7:0] = mem_inst_temp[j][23:16];
    `RTL_MEM.ram6.mem[i][7:0] = mem_inst_temp[j][15: 8];
    `RTL_MEM.ram7.mem[i][7:0] = mem_inst_temp[j][ 7: 0];
    j = j+1;
    `RTL_MEM.ram8.mem[i][7:0] = mem_inst_temp[j][31:24];
    `RTL_MEM.ram9.mem[i][7:0] = mem_inst_temp[j][23:16];
    `RTL_MEM.ram10.mem[i][7:0] = mem_inst_temp[j][15: 8];
    `RTL_MEM.ram11.mem[i][7:0] = mem_inst_temp[j][ 7: 0];
    j = j+1;
    `RTL_MEM.ram12.mem[i][7:0] = mem_inst_temp[j][31:24];
    `RTL_MEM.ram13.mem[i][7:0] = mem_inst_temp[j][23:16];
    `RTL_MEM.ram14.mem[i][7:0] = mem_inst_temp[j][15: 8];
    `RTL_MEM.ram15.mem[i][7:0] = mem_inst_temp[j][ 7: 0];
    j = j+1;
  end
i=0;
for(j=0;i<32'h4000;i=j/4)
  begin
    `RTL_MEM.ram0.mem[i+32'h4000][7:0]  = mem_data_temp[j][31:24];
    `RTL_MEM.ram1.mem[i+32'h4000][7:0]  = mem_data_temp[j][23:16];
    `RTL_MEM.ram2.mem[i+32'h4000][7:0]  = mem_data_temp[j][15: 8];
    `RTL_MEM.ram3.mem[i+32'h4000][7:0]  = mem_data_temp[j][ 7: 0];
    j = j+1;
    `RTL_MEM.ram4.mem[i+32'h4000][7:0]  = mem_data_temp[j][31:24];
    `RTL_MEM.ram5.mem[i+32'h4000][7:0]  = mem_data_temp[j][23:16];
    `RTL_MEM.ram6.mem[i+32'h4000][7:0]  = mem_data_temp[j][15: 8];
    `RTL_MEM.ram7.mem[i+32'h4000][7:0]  = mem_data_temp[j][ 7: 0];
    j = j+1;
    `RTL_MEM.ram8.mem[i+32'h4000][7:0]   = mem_data_temp[j][31:24];
    `RTL_MEM.ram9.mem[i+32'h4000][7:0]   = mem_data_temp[j][23:16];
    `RTL_MEM.ram10.mem[i+32'h4000][7:0]  = mem_data_temp[j][15: 8];
    `RTL_MEM.ram11.mem[i+32'h4000][7:0]  = mem_data_temp[j][ 7: 0];
    j = j+1;
    `RTL_MEM.ram12.mem[i+32'h4000][7:0]  = mem_data_temp[j][31:24];
    `RTL_MEM.ram13.mem[i+32'h4000][7:0]  = mem_data_temp[j][23:16];
    `RTL_MEM.ram14.mem[i+32'h4000][7:0]  = mem_data_temp[j][15: 8];
    `RTL_MEM.ram15.mem[i+32'h4000][7:0]  = mem_data_temp[j][ 7: 0];
    j = j+1;
  end
  $display("\t********* Load program to memory Over! *********");
end


  reg [31:0] cpu_awaddr;
  reg [3:0]  cpu_awlen;
  reg [15:0] cpu_wstrb;
  reg        cpu_wvalid;
  reg [63:0] value0;
  reg [63:0] value1;
  reg [63:0] value2;
  
  
  always @(posedge clk)
  begin
    cpu_awlen[3:0]   <= slave_memory.awlen[3:0];
    cpu_awaddr[31:0] <= slave_memory.mem_addr[31:0];
    cpu_wvalid       <= axi_w_valid;
    cpu_wstrb        <= axi_w_strb;
    value0           <= axi_w_data[63:0];
    value1           <= axi_w_data[127:64];
  end


always @(posedge clk) begin

     if ((cpu_awlen[3:0] == 4'b0) &&
         (cpu_awaddr[31:0] == 32'h01FF_FFF0) &&
          cpu_wvalid
     ) begin
        if(cpu_wstrb[15:0] == 16'hf) 
           begin
              $write("%c", axi_w_data[7:0]);
           end
        else if(cpu_wstrb[15:0] == 16'hf0)
           begin
              $write("%c", axi_w_data[39:32]);
           end
        else if(cpu_wstrb[15:0] == 16'hf00)
           begin
              $write("%c", axi_w_data[71:64]);
           end
        else if(cpu_wstrb[15:0] == 16'hf000)
           begin
              $write("%c", axi_w_data[103:96]);
           end
    end
end

`ifdef VERDI_DUMP
initial begin
      /// method 1: this will dump only ct_top module
      $fsdbDumpon;
      $fsdbDumpvars(0, sim_top);

      /// method 2: this will dump all module
      // $fsdbDumpvars();
end
`endif 

// initial begin
//         #1500000
//         $finish;
// end


top_wrap Top_wrap(
        .clk(clk),
	    .reset(reset),
        .axi_aw_valid(axi_aw_valid),
        .axi_aw_ready(axi_aw_ready),
        .axi_aw_addr(axi_aw_addr),
        .axi_aw_id(axi_aw_id),
        .axi_aw_len(axi_aw_len),
        .axi_aw_size(axi_aw_size),
        .axi_aw_burst(axi_aw_burst),
        .axi_aw_cache(axi_aw_cache),
        .axi_aw_prot(axi_aw_prot),
        .axi_w_valid(axi_w_valid),
        .axi_w_ready(axi_w_ready),
        .axi_w_data(axi_w_data),
        .axi_w_strb(axi_w_strb),
        .axi_w_last(axi_w_last),
        .axi_b_valid(axi_b_valid),
        .axi_b_ready(axi_b_ready),
        .axi_b_id(axi_b_id),
        .axi_b_resp(axi_b_resp),
        .axi_ar_valid(axi_ar_valid),
        .axi_ar_ready(axi_ar_ready),
        .axi_ar_addr(axi_ar_addr),
        .axi_ar_id(axi_ar_id),
        .axi_ar_len(axi_ar_len),
        .axi_ar_size(axi_ar_size),
        .axi_ar_burst(axi_ar_burst),
        .axi_ar_cache(axi_ar_cache),
        .axi_ar_prot(axi_ar_prot),
        .axi_r_valid(axi_r_valid),
        .axi_r_ready(axi_r_ready),
        .axi_r_data(axi_r_data),
        .axi_r_id(axi_r_id),
        .axi_r_resp(axi_r_resp),
        .axi_r_last(axi_r_last),
        .core_in_core_id(core_in_core_id),
        .core_in_interrupt(core_in_interrupt),
        .core_in_ipi(core_in_ipi)
        );

axi_slave128  slave_memory (
  // read address
  .araddr_s0        (axi_ar_addr[39:0] ),
  .arburst_s0       (axi_ar_burst      ),
  .arcache_s0       (axi_ar_cache      ),
  .arid_s0          ({3'b0, axi_ar_id} ),
  .arlen_s0         (axi_ar_len        ),
  .arprot_s0        (axi_ar_prot       ),
  .arready_s0       (axi_ar_ready      ),
  .arsize_s0        (axi_ar_size       ),
  .arvalid_s0       (axi_ar_valid      ),

  .awaddr_s0        (axi_aw_addr[39:0] ),
  .awburst_s0       (axi_aw_burst      ),
  .awcache_s0       (axi_aw_cache      ),
  .awid_s0          ({3'b0, axi_aw_id} ),
  .awlen_s0         (axi_aw_len        ),
  .awprot_s0        (axi_aw_prot       ),
  .awready_s0       (axi_aw_ready      ),
  .awsize_s0        (axi_aw_size       ),
  .awvalid_s0       (axi_aw_valid      ),

  .bid_s0           (axi_b_id          ),
  .bready_s0        (axi_b_ready       ),
  .bresp_s0         (axi_b_resp        ),
  .bvalid_s0        (axi_b_valid       ),

  .pad_cpu_rst_b    (~reset            ),
  .pll_core_cpuclk  (clk               ),

  .rdata_s0         (axi_r_data        ),
  .rid_s0           (axi_r_id          ),
  .rlast_s0         (axi_r_last        ),
  .rready_s0        (axi_r_ready       ),
  .rresp_s0         (axi_r_resp        ),
  .rvalid_s0        (axi_r_valid       ),

  .wdata_s0         (axi_w_data        ),
  .wid_s0           ({8'b0}            ),
  .wlast_s0         (axi_w_last        ),
  .wready_s0        (axi_w_ready       ),
  .wstrb_s0         (axi_w_strb        ),
  .wvalid_s0        (axi_w_valid       )
);

endmodule : sim_top